package Verification;

import Common.*;
import Search.LGSearch;
import Search.LGSearchFindAll;

import java.util.Vector;

public class Benchmark {

	private Graph g;

	private double time;
	private double memory;
	private int occurrences;

	/**
	 * Gets the execution time for the algorithm in milliseconds.
	 *
	 * @return execution time in milliseconds
	 */
	public double getTime() {
		return this.time;
	}

	/**
	 * Gets the memory usage for the algorithm in kilobytes.
	 *
	 * @return memory usage in kilobytes
	 */
	public double getMemory() {
		return this.memory;
	}

	public int getNumberOfOccurrences() {
		return this.occurrences;
	}

	public int run(int nodes, double density, String[] alpha, String[] pattern, boolean findAll) throws Exception {

		// Reset measurement variables
		this.occurrences  = 0;
		this.memory = 0;

		// Take memory footprint sample
		long startMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

		// Create random graph
		g = Graph.randomGraph(nodes, density, alpha);

		try {

			// Start measuring time
			long startTime = System.nanoTime();

			// Pattern throws an exception if the pattern is not a sub-set of the alphabet
			Pattern p = new Pattern(alpha, pattern);

			// Before searching the graph check the pattern
			// is a subset of the graph labels
			boolean patternInLabels = true;
			for (int i = 0; i < pattern.length && patternInLabels; i++) {
				patternInLabels = g.contains(pattern[i]);
			}

			Vector<int[]> seq = new Vector<int[]>();

			if (patternInLabels) {

				// The pattern is contained within the labels of the graph

				if(findAll) {

					LGSearchFindAll search = new LGSearchFindAll(p, g);
					seq = search.Search();

				} else {

					//System.out.println("Initializing single search...");

					LGSearch search = new LGSearch(p, g);
					seq.add(search.Search());
				}

			} else {

				// The pattern is not contained within the labels of the graph

				seq.add(new int[1]);
				seq.elementAt(0)[0] = -1;
			}

			this.time = (System.nanoTime() - startTime) / 1000000.0;

			this.memory = ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) - startMemory) / 1024;

			// Printout of found sequence
			for(int[] entry : seq) {
				if(entry[0] == -1) {
					System.out.println("FAILURE!");
				} else {
					//System.out.println("SUCCESS!!");
					this.occurrences++;
				}
//				for(int node : entry) {
//					System.out.print(Integer.toString(node) + " ");
//				}
//				System.out.print("\n");
			}
		}
		catch(Exception e){System.out.println(e.toString());}

//		System.out.println( "\nStress test..." +
//							"\n   Number of graph nodes: " + Integer.toString(nodes) +
//							"\n   Number of pattern nodes: " + Integer.toString(p.length()) +
//							"\nResulted in..." +
//							"\n   Number of found patterns: " + Integer.toString(occurrences) +
//							"\n   Time eplaced: " + Long.toString(time));

		return occurrences;
	}
}
